/**
 * @Author       : Hejh(3010733382@qq.com)
 * @Version      : V1.0
 * @Date         : 2024-01-17 10:59:06
 * @Description  : 通知接口的验证器
 */

const Joi = require('joi')
const R = require('@/models/Response')
const { ERROR_USER_CODE, ERROR_SYSTEM_CODE } = require('@/constants/errorCode')
const { IS_INTEGER, IS_UNSAFE_INTEGER } = require('@/constants/joiSchema')
const { dumpCheck } = require('@/utils/dumpCheck')

const noticeSchema = {
  noticeIds: Joi.array().items(IS_UNSAFE_INTEGER),
  noticeId: IS_UNSAFE_INTEGER,
  page: IS_INTEGER.min(1).default(1),
  pageSize: IS_INTEGER.min(1).default(999),
  name: Joi.string().min(1).max(50),
  type: IS_INTEGER.valid(0, 1),
  isActive: IS_INTEGER.valid(0, 1),
  level: IS_INTEGER.valid(0, 1),
  content: Joi.string(),
  permissionIds: Joi.array().items(IS_UNSAFE_INTEGER),
  auth: Joi.object({
    all: IS_INTEGER.valid(0, 1).required(),
    depIds: Joi.array().items(IS_UNSAFE_INTEGER).required(),
    roleIds: Joi.array().items(IS_UNSAFE_INTEGER).required(),
    userIds: Joi.array().items(IS_UNSAFE_INTEGER).required()
  }),
  sendTime: Joi.date()
}

/**
 * @description 通知列表查询的参数验证
 * @param {*} ctx
 * @param {*} next
 * @returns
 */
module.exports.listNoticeValidate = async (ctx, next) => {
  const schema = Joi.object({
    page: noticeSchema.page,
    pageSize: noticeSchema.pageSize
  }).validate(ctx.query)

  if (schema.error) {
    ctx.body = R.error(ERROR_SYSTEM_CODE.PARAMS_SCHEMA_ERROR)
    return
  }
  ctx.query = schema.value
  await next()
}

/**
 * @description 通知已读接口的参数验证
 * @param {*} ctx
 * @param {*} next
 * @returns
 */
module.exports.readNoticeValidate = async (ctx, next) => {
  const schema = Joi.object({
    noticeId: noticeSchema.noticeId.required()
  }).validate(ctx.request.body)

  if (schema.error) {
    ctx.body = R.error(ERROR_SYSTEM_CODE.PARAMS_SCHEMA_ERROR)
    return
  }

  const { noticeId } = ctx.request.body

  // 验证noticeId的合法性
  const b2 = await dumpCheck.checkNoticeIds([noticeId])
  if (!b2) {
    ctx.body = R.error(ERROR_USER_CODE.NOTICE_ID_ERROR)
    return
  }

  await next()
}

/**
 * @author: Hejh(3010733382@qq.com)
 * @description: 创建和更新通知时的验证
 * @param {*} ctx koa上下文
 * @param {*} depIds 通知ID数组
 * @param {*} roleIds 角色ID数组
 * @param {array<string>} userIds 权限ID数组
 */
const addAndUpdCheck = async (ctx, depIds, roleIds, userIds) => {
  // 验证部门ID的合法性
  if (depIds !== null) {
    const b4 = await dumpCheck.checkDepPids(depIds, false)
    if (!b4) {
      ctx.body = R.error(ERROR_USER_CODE.DEP_ID_ERROR)
      return false
    }
  }

  // 验证角色ID的合法性
  if (roleIds !== null) {
    const b3 = await dumpCheck.checkRoleIds(roleIds, true, true, 0)
    if (!b3) {
      ctx.body = R.error(ERROR_USER_CODE.ROLE_ID_ERROR)
      return false
    }
  }

  // 验证角色ID数组的合法性
  if (userIds !== null) {
    const b5 = await dumpCheck.checkUserIds(userIds)
    if (!b5) {
      ctx.body = R.error(ERROR_USER_CODE.USER_ID_ERROR)
      return false
    }
  }

  return true
}

/**
 * @description 创建通知时的参数验证
 * @param {*} ctx
 * @param {*} next
 * @returns
 */
module.exports.createNoticeValidate = async (ctx, next) => {
  const schema = Joi.object({
    name: noticeSchema.name.required(),
    content: noticeSchema.content.required(),
    type: noticeSchema.type.required(),
    level: noticeSchema.level.required(),
    isActive: noticeSchema.isActive.required(),
    sendTime: noticeSchema.sendTime.required(),
    auth: noticeSchema.auth.required()
  }).validate(ctx.request.body)

  if (schema.error) {
    ctx.body = R.error(ERROR_SYSTEM_CODE.PARAMS_SCHEMA_ERROR)
    return
  }

  const { auth } = ctx.request.body

  // 如果all不为1，则需要验证其他字段的合法性
  if (!auth.all) {
    // 验证通知名称的合法性
    const { depIds, roleIds, userIds } = auth
    const b = await addAndUpdCheck(ctx, depIds, roleIds, userIds)
    if (!b) {
      return
    }
  }

  // 到这里说明参数没有问题,协作通知情况[0],[-1],[xxx,xxx]
  await next()
}

/**
 * @author: Hejh(3010733382@qq.com)
 * @description: 更新通知时的参数验证
 * @param {*} ctx
 * @param {*} next
 */
module.exports.updateNoticeValidate = async (ctx, next) => {
  const schema = Joi.object({
    noticeId: noticeSchema.noticeId.required(),
    name: noticeSchema.name.required(),
    content: noticeSchema.content.required(),
    type: noticeSchema.type.required(),
    level: noticeSchema.level.required(),
    isActive: noticeSchema.isActive.required(),
    sendTime: noticeSchema.sendTime.required(),
    auth: noticeSchema.auth.required()
  }).validate(ctx.request.body)

  if (schema.error) {
    console.log(schema.error)
    ctx.body = R.error(ERROR_SYSTEM_CODE.PARAMS_SCHEMA_ERROR)
    return
  }

  const {
    noticeId,
    auth: { all, depIds, roleIds, userIds }
  } = ctx.request.body

  // 验证noticeId的合法性
  const b2 = await dumpCheck.checkNoticeIds([noticeId])
  if (!b2) {
    ctx.body = R.error(ERROR_USER_CODE.NOTICE_ID_ERROR)
    return
  }

  // 如果指定对象不为all（所有人）
  if (!all) {
    const b = await addAndUpdCheck(ctx, depIds, roleIds, userIds)
    if (!b) {
      return
    }
  }

  await next()
}

/**
 * @author: Hejh(3010733382@qq.com)
 * @description: 批量删除通知接口的参数验证
 * @param {*} ctx
 * @param {*} next
 */
module.exports.delNoticesValidate = async (ctx, next) => {
  const schema = Joi.object({
    noticeIds: noticeSchema.noticeIds.required()
  }).validate(ctx.request.body)

  if (schema.error) {
    ctx.body = R.error(ERROR_SYSTEM_CODE.PARAMS_SCHEMA_ERROR)
    return
  }

  const { noticeIds } = ctx.request.body

  // 验证通知ID数组的合法性
  const b4 = await dumpCheck.checkNoticeIds(noticeIds)
  if (!b4) {
    ctx.body = R.error(ERROR_USER_CODE.NOTICE_ID_ERROR)
    return
  }

  await next()
}

/**
 * @author: Hejh(3010733382@qq.com)
 * @description: 通知排序接口的参数验证
 * @param {*} ctx
 * @param {*} next
 */
module.exports.sortNoticesValidate = async (ctx, next) => {
  const schema = Joi.object({
    noticeIds: noticeSchema.noticeIds.required()
  }).validate(ctx.request.body)

  if (schema.error) {
    ctx.body = R.error(ERROR_SYSTEM_CODE.PARAMS_SCHEMA_ERROR)
    return
  }

  const { noticeIds } = ctx.request.body

  // 验证通知ID数组的合法性
  const b4 = await dumpCheck.checkNoticeIds(noticeIds)
  if (!b4) {
    ctx.body = R.error(ERROR_USER_CODE.NOTICE_ID_ERROR)
    return
  }

  await next()
}
